package gocache

import (
	"sync"
	"sync/atomic"
	"time"
)

type Item interface {
	Key()string
	Value()interface{}
	LifeSpan(uint64)
	Expiry()uint64
	Free() uint32
	SetFree()
}
type myItem struct {
	sync.RWMutex
	key string
	value interface{}
	lifeSpan uint64
	expiry uint64
	free uint32
}

func (this *myItem)LifeSpan(lifespan uint64){
	atomic.StoreUint64(&this.lifeSpan,lifespan)
}
func (this *myItem)Key()string  {
	return this.key
}
func (this *myItem)Value()interface{}  {
	if atomic.LoadUint32(&this.free) == 1{
		atomic.StoreUint32(&this.free,1)
		return nil
	}
	if  atomic.LoadUint64(&this.expiry)==0{
		return this.value
	}
	if atomic.LoadUint64(&this.expiry) < uint64(time.Now().Unix()){
		expiry := this.expiry
		if atomic.CompareAndSwapUint64(&this.expiry,expiry,expiry){
			atomic.StoreUint32(&this.free,1)
			return nil
		}
	}
	atomic.StoreUint64(&this.expiry,uint64(time.Now().Unix())+atomic.LoadUint64(&this.lifeSpan))
	return this.value
}
func (this *myItem)Expiry()uint64 {
	return atomic.LoadUint64(&this.expiry)
}
func (this *myItem)Free()uint32  {
	return atomic.LoadUint32(&this.free)
}
func (this *myItem)SetFree(){
	atomic.CompareAndSwapUint32(&this.free,0,1)
}
func NewItem(key string,value interface{},lifeSapn uint64)Item{

	return &myItem{
		key:key,
		lifeSpan:lifeSapn,
		expiry:uint64(time.Now().Unix())+lifeSapn,
		value:value,
	}

}